#ifndef _SHA_CRYPTO_H_
#define _SHA_CRYPTO_H_
#include <stdint.h>


#define ENABLE_SHA2_224   1     //if want to use sha224 , set this marco to 1 , else set to 0. 
#define ENABLE_SHA2_256   1     //if want to use sha256 , set this marco to 1 , else set to 0. 
#define ENABLE_SHA2_384   1     //if want to use sha384 , set this marco to 1 , else set to 0. 
#define ENABLE_SHA2_512   1     //if want to use sha512 , set this marco to 1 , else set to 0. 

/*if this macro is true , the crypto_xxx_final() function will output a string. else it will output a hex array*/
#define DIGEST_IS_STRING    0


#if ENABLE_SHA2_224
#if !(DIGEST_IS_STRING)
#define SHA224_DIGEST_LEN 28            // SHA224 outputs a 28 byte digest
#else	/* DIGEST_IS_STRING */
#define SHA224_DIGEST_LEN (28*2 + 1)    // SHA224 outputs a 28*2+1 byte digest for string
#endif	/* DIGEST_IS_STRING */

typedef struct _sha224_ctx_t {
	uint32_t 	total[2];          		/*!< The number of Bytes processed.  */
    uint32_t 	state[8];          		/*!< The intermediate digest state.  */
    uint8_t 	buffer[64];   			/*!< The data block being processed. */
    int32_t		is_224;                 /*!< Determines which function to use:
                                     	     0: Use SHA-256, or 1: Use SHA-224. */
} sha224_ctx_t;

void crypto_sha224_init(sha224_ctx_t *ctx);
void crypto_sha224_update(sha224_ctx_t *ctx, const uint8_t *data, uint32_t len);
void crypto_sha224_final(sha224_ctx_t *ctx, uint8_t *digest);
#endif	/* ENABLE_SHA2_224 */

#if ENABLE_SHA2_256
#if !(DIGEST_IS_STRING)
#define SHA256_DIGEST_LEN 32         	// SHA256 outputs a 32 byte digest
#else	/* DIGEST_IS_STRING */
#define SHA256_DIGEST_LEN (32*2 + 1)    // SHA256 outputs a 32*2+1 byte digest for string
#endif	/* DIGEST_IS_STRING */

typedef struct _sha256_ctx_t {
	uint8_t 			data[64];
	uint32_t 			data_len;
	unsigned long long 	bit_len;
	uint32_t 			state[8];
} sha256_ctx_t;

void crypto_sha256_init(sha256_ctx_t *ctx);
void crypto_sha256_update(sha256_ctx_t *ctx, const uint8_t *data, uint32_t len);
void crypto_sha256_final(sha256_ctx_t *ctx, uint8_t *digest);
#endif	/* ENABLE_SHA2_256 */

#if (ENABLE_SHA2_512) || (ENABLE_SHA2_384)
typedef struct _sha512_ctx_t {
	uint64_t 	total[2];          		/*!< number of bytes processed  */
    uint64_t 	state[8];          		/*!< intermediate digest state  */
    uint8_t 	buffer[128];  			/*!< data block being processed */
    int32_t		is_384;             	/*!< 0 => SHA-512, else SHA-384 */
} sha512_ctx_t;

#if ENABLE_SHA2_384 
#if !(DIGEST_IS_STRING)
#define SHA384_DIGEST_LEN 48         	// SHA384 outputs a 48 byte digest
#else	/* DIGEST_IS_STRING */
#define SHA384_DIGEST_LEN (48*2 + 1)    // SHA384 outputs a 48*2+1 byte digest for string
#endif  /* DIGEST_IS_STRING */

typedef sha512_ctx_t sha384_ctx_t;
void crypto_sha384_init(sha384_ctx_t *ctx);
void crypto_sha384_update(sha384_ctx_t *ctx, const uint8_t *data, uint32_t len);
void crypto_sha384_final(sha384_ctx_t *ctx, uint8_t *digest);
#endif	/* ENABLE_SHA2_384 */

#if ENABLE_SHA2_512
#if !(DIGEST_IS_STRING)
#define SHA512_DIGEST_LEN 64         	// SHA512 outputs a 64 byte digest
#else	/* DIGEST_IS_STRING */
#define SHA512_DIGEST_LEN (64*2 + 1)    // SHA512 outputs a 64*2+1 byte digest for string
#endif  /* DIGEST_IS_STRING */

void crypto_sha512_init(sha512_ctx_t *ctx);
void crypto_sha512_update(sha512_ctx_t *ctx, const uint8_t *data, uint32_t len);
void crypto_sha512_final(sha512_ctx_t *ctx, uint8_t *digest);
#endif	/* ENABLE_SHA2_512 */

#endif	/* (ENABLE_SHA2_512) || (ENABLE_SHA2_384) */

#endif	/* _SHA_CRYPTO_H_ */
